package com.sjd.farm.service.impl;

import com.sjd.common.annotation.lock.LocalLock;
import com.sjd.common.constant.GoldenBeanConstants;
import com.sjd.common.constant.IntegralConstants;
import com.sjd.common.core.domain.AjaxResult;
import com.sjd.common.utils.DateUtils;
import com.sjd.farm.domain.SjdFarmLand;
import com.sjd.farm.domain.SjdFarmLandChange;
import com.sjd.farm.domain.SjdFarmLandClaimOrder;
import com.sjd.farm.domain.dto.land.FarmLandClaimRequestDTO;
import com.sjd.farm.domain.dto.land.FarmLandUpgradeRequestDTO;
import com.sjd.farm.mapper.SjdFarmLandClaimOrderMapper;
import com.sjd.farm.mapper.SjdFarmLandMapper;
import com.sjd.farm.service.ISjdFarmLandChangeService;
import com.sjd.farm.service.ISjdFarmLandClaimOrderService;
import com.sjd.mall.domain.dto.account.InsertIntegralRequestDTO;
import com.sjd.mall.service.account.AccountGoldenBeanService;
import com.sjd.mall.service.account.AccountIntegralService;
import com.sjd.wx.domain.ThirdSession;
import com.sjd.wx.utils.ThirdSessionHolder;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * 农场土地认领订单Service业务层处理
 *
 * @author joker
 * @date 2022-01-26
 */
@Service
@AllArgsConstructor
@Slf4j
public class SjdFarmLandClaimOrderServiceImpl implements ISjdFarmLandClaimOrderService {
    private final SjdFarmLandClaimOrderMapper sjdFarmLandClaimOrderMapper;
    private final SjdFarmLandMapper sjdFarmLandMapper;
    private final ISjdFarmLandChangeService changeService;
    private final AccountGoldenBeanService beanService;
    private final AccountIntegralService integralService;

    @Override
    public List<SjdFarmLandClaimOrder> selectSjdFarmLandClaimOrderList(SjdFarmLandClaimOrder sjdFarmLandClaimOrder) {
        return sjdFarmLandClaimOrderMapper.selectSjdFarmLandClaimOrderList(sjdFarmLandClaimOrder);
    }

    @Override
    public SjdFarmLandClaimOrder getSjdFarmLandClaimOrderById(Long id) {
        return sjdFarmLandClaimOrderMapper.getSjdFarmLandClaimOrderById(id);
    }

    @Override
    public int getMaxLandLevelByMemberId(Long memberId) {
        return sjdFarmLandClaimOrderMapper.getMaxLandLevelByMemberId(memberId);
    }

    @Override
    public String checkFarmLandIsOverDue(LocalDateTime now) {
        // 获取过期订单
        List<SjdFarmLandClaimOrder> waitHandleList = sjdFarmLandClaimOrderMapper.checkOverdueOrder(now);
        int handleCount = waitHandleList.size(), handleSuccess = 0, handleFailure = 0;
        if (handleCount == 0) {
            return "没有过期的订单";
        }
        Set<String> failureSet = new HashSet<>();
        for (SjdFarmLandClaimOrder waitHandle : waitHandleList) {
            try {
                SjdFarmLandClaimOrder waitUpdateOrder = SjdFarmLandClaimOrder.builder()
                        .id(waitHandle.getId()).orderStatus(SjdFarmLandClaimOrder.Param.OVERDUE).build();
                waitUpdateOrder.setRemark("认领单已于" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, waitHandle.getUseEndTime()) + "过期，已回收！！");
                // 订单状态更新为过期
                sjdFarmLandClaimOrderMapper.updateSjdFarmLandClaimOrder(waitUpdateOrder);
                // 土地状态更新为待上架
                SjdFarmLand waitUpdateLand = SjdFarmLand.builder()
                        .landId(waitHandle.getLandId()).landStatus(SjdFarmLand.Param.WAIT_UPDATE)
                        .build();
                waitUpdateLand.setRemark("土地在用户名下过期回收后待上架");
                sjdFarmLandMapper.updateSjdFarmLand(waitUpdateLand);
                // 记录土地变更信息
                String changeTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);
                String changeContent = "编号为" + waitHandle.getLandNo() + "的土地于"
                        + changeTime + "在会员" + waitHandle.getPhone() + "名下过期回收。";
                changeService.insertSjdFarmLandChange(SjdFarmLandChange.builder()
                        .landId(waitHandle.getLandId()).changeType(SjdFarmLandChange.Param.CHANGE_TYPE_RECOVERY)
                        .changeTime(changeTime).changeContent(changeContent)
                        .build());
                handleSuccess++;
            } catch (Exception e) {
                handleFailure++;
                failureSet.add(waitHandle.getId() + ":" + e.getMessage());
            }
        }
        return "任务处理结果，处理总数" + handleCount + "条,处理成功" +
                handleSuccess + "条，处理失败" + handleFailure + "条，失败明细：" + failureSet;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LocalLock(key = "land:claim:args[0]", errMsg = "您好，当前土地已被其他会员认领，请您重新选择土地认领", isExpress = true)
    public AjaxResult farmLandClaim(Long landId, FarmLandClaimRequestDTO requestDTO) {
        ThirdSession thirdSession = ThirdSessionHolder.getThirdSession();
        SjdFarmLand sjdFarmLand = sjdFarmLandMapper.selectSjdFarmLandByLandId(landId);
        if (Objects.isNull(sjdFarmLand) || SjdFarmLand.Param.SALE != sjdFarmLand.getLandStatus()) {
            return AjaxResult.error("当前土地已下架或被他人认领，请您重新选择土地认领。");
        }
        if (requestDTO.getBeanCount().compareTo(sjdFarmLand.getLandPrice()) != 0) {
            return AjaxResult.error("支付金豆数量和土地售卖金豆数量不一致，请检查！！");
        }
        // 确定使用时间
        LocalDateTime userStartTime = LocalDateTime.now();
        LocalDateTime useEndTime = userStartTime.plusMonths(sjdFarmLand.getUsedLimit());
        // 扣减金豆数量
        String remark = "认领土地消费金豆数量：" + requestDTO.getBeanCount() + "，认领期限：" + sjdFarmLand.getUsedLimit() + "个月";
        AjaxResult beanResult = beanService.createConsumeOrRefoundOrder(GoldenBeanConstants.CONSUME_LAND, requestDTO.getBeanCount(), remark);
        if (!beanResult.isSuccess()) {
            return beanResult;
        }
        // 保存认领订单
        SjdFarmLandClaimOrder order = SjdFarmLandClaimOrder.builder()
                .landId(landId).memberId(thirdSession.getMemberId()).orderStatus(SjdFarmLandClaimOrder.Param.NORMAL)
                .landLevel(0).consumeAmount(requestDTO.getBeanCount())
                .useStartTime(userStartTime).useEndTime(useEndTime)
                .landRenewalCount(0)
                .build();
        order.setRemark(remark);
        sjdFarmLandClaimOrderMapper.insertSjdFarmLandClaimOrder(order);
        // 更新土地状态为已认领
        sjdFarmLandMapper.updateSjdFarmLand(SjdFarmLand.builder()
                .landId(landId).landStatus(SjdFarmLand.Param.CLAIM)
                .build());
        // 保存土地变更记录
        String changeTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, userStartTime);
        String changeContent = "编号为" + sjdFarmLand.getLandNo() + "的土地，在"
                + changeTime + "被会员" + thirdSession.getMobile() + "认领，认领金豆数量为："
                + requestDTO.getBeanCount() + ",认领期限为" + sjdFarmLand.getUsedLimit() + "个月";
        changeService.insertSjdFarmLandChange(SjdFarmLandChange.builder()
                .landId(landId).changeType(SjdFarmLandChange.Param.CHANGE_TYPE_SALE)
                .changeTime(changeTime).changeContent(changeContent)
                .build());
        return AjaxResult.success("认领成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LocalLock(key = "land:upgrade:args[0]", errMsg = "您好，当前土地正在升级，请稍后", isExpress = true)
    public AjaxResult farmLandUpgrade(Long claimOrderId, FarmLandUpgradeRequestDTO requestDTO) {
        // 获取订单校验相关信息
        SjdFarmLandClaimOrder claimOrder = getSjdFarmLandClaimOrderById(claimOrderId);
        if (Objects.isNull(claimOrder) || SjdFarmLandClaimOrder.Param.OVERDUE.equals(claimOrder.getOrderStatus())) {
            return AjaxResult.error("当前土地状态不允许进行升级操作");
        }
        if (requestDTO.getIntegralCount().compareTo(claimOrder.getUpgradeNeedIntegral()) != 0) {
            return AjaxResult.error("升级积分和升级所需积分不一致，请检查！！");
        }
        // 确定新等级
        int oldLevel = claimOrder.getLandLevel();
        int newLevel = oldLevel + 1;
        // 扣减用户积分
        String remark = "用户于" + DateUtils.getTime() + "升级土地，等级由" +
                oldLevel + "级升为" + newLevel + "级，消费积分" + requestDTO.getIntegralCount();
        InsertIntegralRequestDTO integralRequestDTO = new InsertIntegralRequestDTO();
        integralRequestDTO.setIntegralNum(requestDTO.getIntegralCount());
        integralRequestDTO.setIntergralType(IntegralConstants.CONSUME);
        integralRequestDTO.setDescription(remark);
        AjaxResult ajaxResult = integralService.insertIntegralDetail(integralRequestDTO);
        if (!ajaxResult.isSuccess()) {
            return ajaxResult;
        }
        // 积分扣减成功升级土地
        SjdFarmLandClaimOrder waitUpdate = SjdFarmLandClaimOrder.builder().id(claimOrderId).landLevel(newLevel).build();
        waitUpdate.setRemark(remark);
        sjdFarmLandClaimOrderMapper.updateSjdFarmLandClaimOrder(waitUpdate);
        return AjaxResult.success("升级成功");
    }
}
